package com.ruoyi.web.controller.app;

import cn.dev33.satoken.annotation.SaIgnore;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.app.domain.AppVipCard;
import com.ruoyi.app.domain.AppVipOrder;
import com.ruoyi.app.domain.bo.AppVipCardBo;
import com.ruoyi.app.domain.bo.AppVipOrderBo;
import com.ruoyi.app.domain.vo.AppUserVo;
import com.ruoyi.app.domain.vo.AppVipCardVo;
import com.ruoyi.app.domain.vo.AppVipOrderVo;
import com.ruoyi.app.domain.vo.AppVipTypeVo;
import com.ruoyi.app.service.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BillType;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.CoinType;
import com.ruoyi.common.enums.DetailEnums;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ios.IosVerify;
import com.ruoyi.framework.config.properties.PayUrlProperties;
import com.ruoyi.web.service.pay.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jdom2.JDOMException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * APP会员VIP订单
 *
 * @author heike
 * @date 2025-03-17
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/vipOrder")
@Slf4j
public class AppVipOrderController extends BaseController {


    private final IAppUserService appUserService;
    private final IAppAssetService appAssetService;
    private final IAppDetailService appDetailService;
    private final IAppUserVipService iAppUserVipService;
    private final IAppVipTypeService iAppVipTypeService;
    private final IAppVipOrderService iAppVipOrderService;
    private final WxPayService wsPayService;
    private final PayUrlProperties payUrlProperties;
    private final IAppVipCardService appVipCardService;


    /**
     * 查询APP会员VIP订单列表
     */
    @GetMapping("/list")
    public TableDataInfo<AppVipOrderVo> list(AppVipOrderBo bo, PageQuery pageQuery) {
        return iAppVipOrderService.queryPageList(bo, pageQuery);
    }

    /**
     * 获取APPv会员VIP订单详细信息
     *
     * @param id 主键
     */
    @GetMapping("/{id}")
    public R<AppVipOrderVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
        return R.ok(iAppVipOrderService.queryById(id));
    }

    /**
     * APP会员VIP下单
     */
    @Log(title = "APP会员VIP订单", businessType = BusinessType.INSERT)

    @PostMapping()
    public R<AppVipOrder> add(@RequestParam(name = "vipId") Long vipId) {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        AppVipTypeVo appVipTypeVo = iAppVipTypeService.queryById(vipId);
        if (Objects.isNull(appVipTypeVo)) {
            return R.fail("记录ID错误！");
        }
        return R.ok(iAppVipOrderService.createOrder(appVipTypeVo, id));
    }

    /**
     * VIP支付签名
     *
     * @param payType 支付类型
     * @param orderNo 订单号
     * @return
     */
    @PostMapping("sign")
    public R<Object> sign(@RequestParam(name = "payType") Integer payType,
                          @RequestParam(name = "orderNo") String orderNo,
                          @RequestParam(name = "code", required = false) String code,
                          HttpServletRequest request) throws Exception {
        Map<String, String> params = new HashMap<>(2);
        AppVipOrderVo vipOrder = iAppVipOrderService.queryOrderNo(orderNo);
        if (Objects.isNull(vipOrder)) {
            return R.fail("订单号错误！");
        }
        if (!StringUtils.equals(vipOrder.getStatus(), Constants.SUCCESS)) {
            return R.fail("订单已处理！");
        }
        AppVipTypeVo vipPackage = iAppVipTypeService.queryById(vipOrder.getVipId());
        Map<String, String> map = new LinkedHashMap<>();
        params.put("body", "全能帮手");
        params.put("subject", "全能帮手");
        params.put("tradeNo", orderNo);
        params.put("amount", BigDecimal.valueOf(vipPackage.getAndroidPrice()).stripTrailingZeros().toPlainString());
        if (1 == payType) {
            params.put("notifyUrl", payUrlProperties.getAlipayNotifyUrl());
            String sign = AlipayCertService.creatOrder(params);
            map.put("sign", sign);
            log.info("支付宝参数：{}", params);
            log.info("支付宝签名SIGN：{}", sign);
            return R.ok(map);
        }
        if (2 == payType) {
            params.put("attach", null);
            params.put("notifyUrl", payUrlProperties.getWechatNotifyUrl());
            Map<String, String> signParam = WxPayCertService.createAppPayment(params, request);
            log.info("微信参数：{}", params);
            log.info("微信支付签名SIGN：{}", signParam);
            return R.ok(signParam);
        }
        if (4 == payType) {
            Boolean success = appAssetService.subtractIntegral(vipOrder.getUserId(), BigDecimal.valueOf(vipPackage.getDiscount()));
            if (success) {
                appDetailService.insert(vipOrder.getUserId(), new BigDecimal(vipPackage.getDiscount()), BigDecimal.ZERO, BillType.TO.getCode(), CoinType.INTE.getCode(), DetailEnums.CHANGE.getCode(), "兑换会员", null);
                iAppUserVipService.addVipTime(vipOrder, null, null, "integral");
                return R.ok("支付成功");
            }
        }
        return R.fail("签名错误！");
    }


    /**
     * 归属我的会员卡列表
     *
     * @return
     */
    @GetMapping("/getCardList")
    public R<?> getCardList() {
        AppVipCardBo vipCardBo = new AppVipCardBo();
        vipCardBo.setCardUser(getUserId());
        vipCardBo.setStaus(Constants.SUCCESS);
        List<AppVipCardVo> vipCardVos = appVipCardService.queryList(vipCardBo);
        Map<String, List<AppVipCardVo>> collect = vipCardVos.stream().filter(e -> e.getCardEndTime().getTime() > System.currentTimeMillis()).collect(Collectors.groupingBy(AppVipCardVo::getCardName));
        ArrayList<AppVipCardVo> list = new ArrayList<>();
        for (String k : collect.keySet()) {
            List<AppVipCardVo> cardVos = collect.get(k);
            AppVipCardVo appVipCardVo = cardVos.get(0);
            appVipCardVo.setSumNumber(cardVos.size());
            list.add(appVipCardVo);
        }
        list.sort(Comparator.comparing(AppVipCardVo::getCreateTime));
        return R.ok(list);
    }

    /**
     * 赠送会员卡
     *
     * @return
     */
    @PostMapping("/sendCard")
    public R<?> sendCard(
        @RequestParam(name = "number", defaultValue = "1") Integer number,
        @RequestParam(name = "cardPhone") String cardPhone,
        @RequestParam(name = "cardName") String cardName
    ) {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        AppUserVo userVo = appUserService.queryByPhone(cardPhone);
        if (Objects.isNull(userVo)) {
            return R.fail("赠送用户不存在！");
        }
        if (userVo.getId().equals(id)) {
            return R.fail("不能赠送给自己！");
        }
        LambdaQueryWrapper<AppVipCard> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppVipCard::getCardUser, id);
        wrapper.eq(AppVipCard::getCardName, cardName);
        wrapper.eq(AppVipCard::getStaus, Constants.SUCCESS);
        wrapper.gt(AppVipCard::getCardEndTime, new Date());
        List<AppVipCardVo> vipCardVos = appVipCardService.queryList(wrapper);
        if (vipCardVos.size() < number) {
            return R.fail("广告卡数量不足！");
        }
        List<AppVipCardVo> resultCardVos = vipCardVos.subList(0, number);
        Boolean result = appVipCardService.sendCard(resultCardVos, userVo.getId());
        return result ? R.ok("赠送成功") : R.fail("赠送失败");
    }


    /**
     * 直接激活一张会员卡
     *
     * @return
     */
    @PostMapping("/activate")
    public R<?> activate() {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        LambdaQueryWrapper<AppVipCard> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppVipCard::getCardUser, id);
        wrapper.eq(AppVipCard::getStaus, Constants.SUCCESS);
        wrapper.gt(AppVipCard::getCardEndTime, new Date());
        List<AppVipCardVo> vipCardVos = appVipCardService.queryList(wrapper);
        if (vipCardVos.isEmpty()) {
            return R.fail("广告卡数量不足！");
        }
        AppVipCardVo appVipCardVo = vipCardVos.get(0);
        iAppUserVipService.addVipTime(appVipCardVo, id, appVipCardVo.getCardDay());
        return R.ok("激活成功");
    }


    /**
     * 激活会员卡
     *
     * @param cardNumber 会员卡号
     * @return
     */
    @PostMapping("/activateCard")
    public R<?> activateCard(@RequestParam(name = "cardNumber") String cardNumber) {
        if (StringUtils.isBlank(cardNumber)) {
            return R.fail("激活卡号不能为空！");
        }
        AppVipCardVo appVipCardVo = appVipCardService.queryCardNumber(cardNumber);
        if (Objects.isNull(appVipCardVo)) {
            return R.fail("激活失败，广告卡不存在！");
        }
        if (appVipCardVo.getCardEndTime().before(new Date())) {
            return R.fail("激活失败，广告卡已过期！");
        }
        if (StringUtils.equals(appVipCardVo.getStaus(), Constants.FAIL)) {
            return R.fail("激活失败，广告卡已使用！");
        }
        iAppUserVipService.addVipTime(appVipCardVo, getUserId(), appVipCardVo.getCardDay());
        return R.ok("激活成功");
    }


    /**
     * VIP充值支付宝回调
     * 证书模式验证
     *
     * @param request 回调参数
     * @return
     */
    @SaIgnore
    @PostMapping("/aliPayCallBack")
    public String aliPayCallBack(HttpServletRequest request) throws Exception {
        Map<String, String[]> parameterMap = request.getParameterMap();
        StringBuilder notifyBuild = new StringBuilder("/****************************** alipay notify ******************************/\n");
        parameterMap.forEach((key, value) -> notifyBuild.append(key + "=" + value[0] + "\n"));
        log.info(notifyBuild.toString());
        log.info("通知回调：支付宝回调日志信息信息：" + request.getParameterMap().toString());
        if (AlipayUtil.rsaCheckV1(request)) {
            String lCharset = "ISO-8859-1";
            String rCharset = "UTF-8";
            String tradeStatus = new String(request.getParameter("trade_status").getBytes(lCharset), rCharset);
            // 商户订单号
            String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(lCharset), rCharset);
            // 支付宝交易号
            String tradeNo = new String(request.getParameter("trade_no").getBytes(lCharset), rCharset);
            if ("TRADE_SUCCESS".equalsIgnoreCase(tradeStatus)) {
                AppVipOrderVo vipOrder = iAppVipOrderService.queryOrderNo(outTradeNo);
                if (vipOrder != null && vipOrder.getStatus().equals(Constants.SUCCESS)) {
                    iAppUserVipService.addVipTime(vipOrder, tradeNo, outTradeNo, "alipay");
                    log.info("开通VIP支付宝回调成功");
                    return "success";
                }
            }
        }
        return "failure";
    }

    /**
     * VIP充值支付宝回调
     * 非证书模式验证
     *
     * @param request 回调参数
     * @return
     */
    @SaIgnore
    @PostMapping("aliPayCallBack_back")
    public String aliPayCallBack_back(HttpServletRequest request) {
        try {
            Map<String, String> result = AlipayService.getAlipayResult(request);
            log.info("开通VIP支付宝回调返回信息：{}", result);
            if (AlipayService.verify(result) && AlipayService.check(result)) {
                if ("TRADE_SUCCESS".equals(result.get("trade_status"))) {
                    //外部订单号
                    String tradeNo = result.get("trade_no");
                    //内部订单号
                    String outTradeNo = result.get("out_trade_no");
                    AppVipOrderVo vipOrder = iAppVipOrderService.queryOrderNo(outTradeNo);
                    if (vipOrder != null && vipOrder.getStatus().equals(Constants.SUCCESS)) {
                        iAppUserVipService.addVipTime(vipOrder, tradeNo, outTradeNo, "alipay");
                        log.info("开通VIP支付宝回调成功");
                        return "success";
                    }
                }
            } else {
                log.info("开通VIP支付宝回调签名验证失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("开通VIP支付宝回调失败！");
        }
        return "failure";
    }

    /**
     * VIP充值微信回调
     * 证书模式验证
     *
     * @param request 回调参数
     * @return String
     */
    @SaIgnore
    @PostMapping("/wxPayCallBack")
    public String wxPayCallBack(HttpServletRequest request) throws IOException {
        log.info("微信支付回调开始");
        String resXml = "<xml><return_code>FAIL</return_code><return_msg>OK</return_msg></xml>";
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultxml = new String(outSteam.toByteArray(), "utf-8");
        Map<String, String> params = null;
        try {
            params = WxPayCertService.doXMLParse(resultxml);
        } catch (JDOMException e) {
            e.printStackTrace();
        }
        outSteam.close();
        inStream.close();
        if (WxPayCertService.isTenpaySign(params)) {
            log.info("=================================微信付款回调验证成功=================================");
            // 获取内部订单编号
            String outTradeNo = params.get("out_trade_no");
            String tradeNo = params.get("transaction_id");
            String returnCode = params.get("return_code");
            if ("SUCCESS".equals(returnCode)) {
                AppVipOrderVo vipOrder = iAppVipOrderService.queryOrderNo(outTradeNo);
                if (vipOrder != null && vipOrder.getStatus().equals(Constants.SUCCESS)) {
                    iAppUserVipService.addVipTime(vipOrder, tradeNo, outTradeNo, "weChat");
                    log.info("=================================微信支付回调业务处理完毕=================================");
                    return "<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>";
                }
            }
        }
        // 支付回调失败
        log.info("=================================付款回调验证失败=================================");
        return resXml;
    }

    /**
     * VIP充值微信回调
     * 无证书模式验证
     *
     * @param request 回调参数
     * @return
     */
    @SaIgnore
    @PostMapping("/wxPayCallBack_Back")
    public void wxPayCallBack_Back(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[";
        log.info("微信开通VIP支付回调开始：");
        BufferedOutputStream out = null;
        String notityXml = "";
        try {
            String inputLine;
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml = notityXml + inputLine;
            }
            request.getReader().close();
            Map<String, String> paramMap = wsPayService.doXMLParse(notityXml);
            log.info("微信回调数据：{}", paramMap.toString());
            String tradeNo = paramMap.get("transaction_id");
            String outTradeNo = paramMap.get("out_trade_no");
            if ("SUCCESS".equals(paramMap.get("return_code"))) {
                AppVipOrderVo vipOrder = iAppVipOrderService.queryOrderNo(outTradeNo);
                if (vipOrder != null && vipOrder.getStatus().equals(Constants.SUCCESS)) {
                    iAppUserVipService.addVipTime(vipOrder, tradeNo, outTradeNo, "weChat");
                    resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml> ";
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
        wsPayService.sendToCFT(resXml, response);
    }

    /**
     * 苹果开通VIP支付调用
     *
     * @param orderNo 订单号
     * @param receipt 苹果数据
     * @return
     */
    @PostMapping("iosPaySuccess")
    public R<Object> iosPaySuccess(@RequestParam("orderNo") String orderNo, @RequestParam("receipt") String receipt) {
        Map<String, Object> result;
        try {
            receipt = URLDecoder.decode(receipt, "utf-8");
            log.info("----------------------开通VIP功能苹果返回数据:" + receipt);
            result = IosVerify.buyAppVerify(receipt);
            boolean success = (boolean) result.get("success");
            if (!success) {
                return R.fail("签名验证错误");
            }
            log.info("----------------------苹果支付解密数据:" + result);
            String productId = result.get("product_id").toString();
            String externalOrderNo = result.get("entity").toString();
            AppVipOrderVo vipOrder = iAppVipOrderService.queryOrderNo(orderNo);
            if (Objects.isNull(vipOrder) || vipOrder.getStatus().equals(Constants.FAIL)) {
                return R.fail("订单不存在或已处理");
            }
            AppVipTypeVo appVipTypeVo = iAppVipTypeService.queryById(vipOrder.getVipId());
            if (!appVipTypeVo.getIosName().equals(productId)) {
                return R.fail("充值金额和套餐不一致!");
            }
            iAppUserVipService.addVipTime(vipOrder, externalOrderNo, orderNo, "ios");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return R.ok("成功");
    }
}
